#pragma once
#include <cmath>
#include "Vector3.h"

namespace Math
{

class CQuaternion
{
public:

	union 
	{
		struct
		{
			float _w, _x, _y, _z;
		};
		float q[4];
	};
	
	CQuaternion();
	CQuaternion(float w, float x, float y, float z);
	CQuaternion(float w, const CVector3& vec);
	CQuaternion(const CQuaternion& rhs);
	~CQuaternion(void);

	CQuaternion& operator=(const CQuaternion& rhs);

	CQuaternion  operator-(void);					//Inverse
	CQuaternion  operator-(const CQuaternion& rhs);	//Sub
	CQuaternion  operator*(const CQuaternion& rhs);	//Multiply

	CQuaternion& operator*=(const CQuaternion& rhs);
	CQuaternion& operator-=(const CQuaternion& rhs);

	bool		 IsZore(void)const;

	float		 Module(void);
	void		 Normalize(void);
	void		 Identity(void);
	void		 Inverse(void);
	void         Opposite(void);
	float		 GetRotateAngle(void)const;
	CVector3     GetRotationAxis(void)const;

	void		 Yaw(float angle);
	void		 Pitch(float angle);
	void         Roll(float angle);
	void		 Rotate(const CVector3& n, float angle);
	void		 RotateYawPitchRoll(float yaw, float pitch, float roll);
	

	static  void  Multiply(MATH_OUT CQuaternion* pRes, const CQuaternion* pLhs, const CQuaternion* pRhs);
	static  float Dot(const CQuaternion* pLhs, const CQuaternion* pRhs);
	static  void  Inverse(MATH_OUT CQuaternion* pRes, const CQuaternion* pLhs);
	static  void  Sub(MATH_OUT CQuaternion* pRes, const CQuaternion* pLhs, const CQuaternion* pRhs);
	static  void  Pow(MATH_OUT CQuaternion* pRes, const CQuaternion* pLhs, float pow);
	static  void  Slerp(MATH_OUT CQuaternion* pRes, const CQuaternion* pLhs, const CQuaternion* pRhs, float t);
	
};

}